package com.tools.web.interceptor.auth;

import com.fasterxml.jackson.core.type.TypeReference;
import com.tools.common.container.MapEnum;
import com.tools.common.container.OwnPairs;
import com.tools.common.container.RowKit;
import com.tools.common.container.r.OnlyReadArrayList;
import com.tools.common.container.r.OnlyReadHashMap;
import com.tools.common.object.C;
import com.tools.common.object.Note;
import com.tools.common.object.ObjKit;
import com.tools.common.object.json.JsonKit;
import com.tools.common.object.string.VerifyKit;

import java.util.*;

/**
 * 通用用户认证信息的对象的抽象实现
 * */
@Note("通用用户认证信息的对象的抽象实现")
public abstract class GenericAuthUser implements AuthUser {

    @Note("UUID 标识前缀，标识这是某一条登录记录（一般用于存储在缓存中才使用）")
    private String uuid;

    @Note("用户/账户 ID")
    private Object userId;

    @Note("客户端登录设备类型 ID")
    private String loginDeviceType;

    @Note("登录用户的类型标字符串标识（比如平台用户、小程序用户等等）")
    private String loginUserType;

    @Note("用户实体的具体类型")
    private Class<?> userTypeClass;

    @Note("用户实体数据")
    private Object user;

    @Note("角色 key 与角色名称/对象的 Map 集合")
    private Map<String, ?> roleKeyMap;

    @Note("权限 key 与权限名称/对象的 Map 集合")
    private Map<String, ?> permKeyMap;

    @Note("用户/账户的前端路由列表的 JSON 字符串，将其缓存到 token 的缓存容器里以减轻查询数据库的压力")
    private List<?> routerList;

    @Note("若还需要存储额外的数据，可以保存至这里")
    private Map<String, Object> customData;

    /* **************************************************************************************
     *
     *          构造器
     *
     * **************************************************************************************
     * */

    protected GenericAuthUser(Object userId, String loginDeviceType, Object user,
                              Map roleKeyMap, Map permissionIds,
                              Iterable routers) {
        this.setUserId(userId);
        this.setLoginDeviceType(loginDeviceType);
        this.setUser(user);
        this.setRoleKeyMap(roleKeyMap);
        this.setPermKeyMap(permissionIds);
        this.setRouterList(routers);
    }

    /* **************************************************************************************
     *
     *          Getter/Setter
     *
     * **************************************************************************************
     * */

    @Override
    public String getUuid() {
        return uuid;
    }

    @Override
    public void setUuid(String uuid) {
        if(uuid != null && !uuid.isEmpty()) {
            this.uuid = uuid;
            return;
        }
        throw new IllegalArgumentException("不能设置空的 uuid 作为 AuthToken 的标识");
    }

    @Override
    public final Object getUserId() {
        return userId;
    }

    @Override
    public final String stringUserId() {
        return userId.toString();
    }

    @Override
    public long longUserId() {
        if(userId instanceof Long) {
            return (Long) userId;
        }
        if(userId instanceof String) {
            long id = Long.parseLong((String) userId);
            this.userId = id;
            return id;
        }
        int id = (Integer) userId;
        this.userId = id;
        return id;
    }

    @Override
    public int intUserId() {
        if(userId instanceof Integer) {
            return (Integer) userId;
        }
        if(userId instanceof String) {
            int id = Integer.parseInt((String) userId);
            this.userId = id;
            return id;
        }
        int id = ((Long) userId).intValue();
        this.userId = id;
        return id;
    }

    @Override
    public void setUserId(Object userId) {
        if(userId instanceof String || userId instanceof Long || userId instanceof Integer) {
            this.userId = userId;
            return;
        }
        throw new IllegalArgumentException("userId 仅支持字符串、int、long 类型");
    }

    @Override
    public void setUserId(String userId) {
        if(userId != null) {
            this.userId = userId;
            return;
        }
        throw new NullPointerException("userId 不能设置为 null");
    }

    @Override
    public void setUserId(long userId) {
        this.userId = userId;
    }

    @Override
    public void setUserId(int userId) {
        this.userId = userId;
    }

    @Override
    public String getLoginDeviceType() {
        return loginDeviceType;
    }

    @Override
    public void setLoginDeviceType(String loginDeviceType) {
        if(loginDeviceType != null) {
            this.loginDeviceType = loginDeviceType;
            return;
        }
        throw new NullPointerException("不能设置 null 的设备类型");
    }

    @Override
    public void setLoginDeviceType(LoginDeviceType loginDeviceType) {
        if(loginDeviceType != null) {
            this.loginDeviceType = loginDeviceType.getValue();
            return;
        }
        throw new NullPointerException("不能设置 null 的设备类型");
    }

    @Override
    public String getLoginUserType() {
        return loginUserType;
    }

    @Override
    public void setLoginUserType(String loginUserType) {
        this.loginUserType = (loginUserType != null) ? loginUserType : "";
    }

    public Class<?> getUserTypeClass() {
        return userTypeClass;
    }

    @Override
    public void setUserTypeClass(String userTypeClassName) {
        this.userTypeClass = ObjKit.getObjectClass(userTypeClassName);
    }

    @Override
    public void setUserTypeClass(Class<?> userTypeClass) {
        this.userTypeClass = Objects.requireNonNull(userTypeClass, "用户数据类型 Class 不能设置为 null");
    }

    @Override
    public Object getUser() {
        return user;
    }

    @Override
    public <T> T getUser(Class<T> userType) {
        return (T) user;
    }

    @Override
    public <T> T getUser(C<T> userType) {
        return (T) ObjKit.toRealValue(this.user, userType);
    }

    @Override
    public void setUser(Object user) {
        this.user = user;
        if(user != null) {
            this.userTypeClass = user.getClass();
            return;
        }
        this.userTypeClass = null;
    }

    @Override
    public final Map<String, ?> getRoleKeyMap() {
        return roleKeyMap;
    }

    @Override
    public final <R> Map<String, R> getRoleKeyMap(Class<R> valueType) {
        return (Map<String, R>) roleKeyMap;
    }

    @Override
    public final Set<String> roleKeySet() {
        if(roleKeyMap != null && !roleKeyMap.isEmpty()) return new HashSet<>(roleKeyMap.keySet());
        return new HashSet<>();
    }

    @Override
    public final Collection<?> roleValueCollection() {
        if(roleKeyMap != null && !roleKeyMap.isEmpty()) return new ArrayList<>(roleKeyMap.values());
        return new ArrayList<>();
    }

    @Override
    public final <R> Collection<R> roleValueCollection(Class<R> valueType) {
        return (Collection<R>) this.roleValueCollection();
    }

    @Override
    public final <R> Collection<R> roleValueCollection(C<R> valueType) {
        return RowKit.toArrayList(this.roleValueCollection(), valueType);
    }

    @Override
    public final Map<String, ?> cloneRoleKeyMap() {
        return (this.permKeyMap != null && !this.permKeyMap.isEmpty())
                ? new HashMap<>(this.permKeyMap)
                : new HashMap<>();
    }

    @Override
    public final <R> Map<String, R> cloneRoleKeyMap(Class<R> valueType) {
        return (Map<String , R>) this.cloneRoleKeyMap();
    }

    @Override
    public final <R> Map<String, R> cloneRoleKeyMap(C<R> valueType) {
        if(roleKeyMap != null && !roleKeyMap.isEmpty()) {
            Map<String, R> result = new HashMap<>((int) (roleKeyMap.size() / 0.75) + 1);
            for(Map.Entry<String, ?> e : roleKeyMap.entrySet()) {
                result.put(e.getKey(), (R) ObjKit.toRealValue(e.getValue(), valueType));
            }
            return result;
        }
        return new HashMap<>();
    }

    @Override
    public final void setRoleKeyMap(Map roleKeyMap) {
        Map<String, Object> temp = this.private_getTempMap(roleKeyMap);
        this.roleKeyMap = temp != null
                ? new OnlyReadHashMap<>(temp)
                : null;
    }

    @Override
    public final void setRoleKeyMap(OwnPairs roleKeyPairs) {
        Map<String, Object> temp = this.private_getTempMap(roleKeyPairs);
        this.roleKeyMap = temp != null
                ? new OnlyReadHashMap<>(temp)
                : null;
    }

    @Override
    public final Map<String , ?> getPermKeyMap() {
        return permKeyMap;
    }

    @Override
    public final <P> Map<String, P> getPermKeyMap(Class<P> valueType) {
        return (Map<String , P>) permKeyMap;
    }

    @Override
    public final Set<String> permKeySet() {
        if(permKeyMap != null && !permKeyMap.isEmpty()) return new HashSet<>(permKeyMap.keySet());
        return new HashSet<>();
    }

    @Override
    public final Collection<?> permValueCollection() {
        if(permKeyMap != null && !permKeyMap.isEmpty()) return new ArrayList<>(permKeyMap.values());
        return new ArrayList<>();
    }

    @Override
    public final <P> Collection<P> permValueCollection(Class<P> valueType) {
        return (Collection<P>) this.permValueCollection();
    }

    @Override
    public final <P> Collection<P> permValueCollection(C<P> valueType) {
        return RowKit.toArrayList(this.permValueCollection(), valueType);
    }

    @Override
    public final Map<String, ?> clonePermKeyMap() {
        return (this.permKeyMap != null && !this.permKeyMap.isEmpty())
                ? new HashMap<>(this.permKeyMap)
                : new HashMap<>();
    }

    @Override
    public final  <P> Map<String, P> clonePermKeyMap(Class<P> valueType) {
        return (Map<String , P>) this.clonePermKeyMap();
    }

    @Override
    public final  <P> Map<String, P> clonePermKeyMap(C<P> valueType) {
        if(permKeyMap != null && !permKeyMap.isEmpty()) {
            Map<String, P> result = new HashMap<>((int) (permKeyMap.size() / 0.75) + 1);
            Set<? extends Map.Entry<String, ?>> entries = permKeyMap.entrySet();
            for(Map.Entry<String, ?> e : entries) {
                result.put(e.getKey(), (P) ObjKit.toRealValue(e.getValue(), valueType));
            }
            return result;
        }
        return new HashMap<>();
    }

    @Override
    public final void setPermKeyMap(Map permKeyMap) {
        Map<String, Object> temp = this.private_getTempMap(permKeyMap);
        this.permKeyMap = temp != null
                ? new OnlyReadHashMap<>(temp)
                : null;
    }

    @Override
    public final void setPermKeyMap(OwnPairs permKeyPairs) {
        Map<String, Object> temp = this.private_getTempMap(permKeyPairs);
        this.permKeyMap = temp != null
                ? new OnlyReadHashMap<>(temp)
                : null;
    }

    @Override
    public final List<?> getRouterList() {
        return routerList;
    }

    @Override
    public final <R> List<R> getRouterList(Class<R> routerType) {
        return (List<R>) routerList;
    }

    @Override
    public final List<?> cloneRouterList() {
        return (this.routerList != null && !this.routerList.isEmpty())
                ? new ArrayList<>(this.routerList)
                : new ArrayList<>();
    }

    @Override
    public final <R> List<R> cloneRouterList(Class<R> routerType) {
        return (List<R>) this.cloneRouterList();
    }

    @Override
    public final <R> List<R> cloneRouterList(C<R> routerType) {
        return RowKit.toArrayList(routerType, routerList);
    }

    @Override
    public final void setRouterList(Iterable routerList) {
        this.routerList = new OnlyReadArrayList<>(routerList);
    }

    @Override
    public Map<String, Object> cloneCustomData() {
        return (customData != null && !customData.isEmpty())
                ? new HashMap<>(this.customData)
                : new HashMap<>();
    }

    @Override
    public <T> T customDataAsJavaBean(C<T> javaBeanType) {
        return ObjKit.buildObject(javaBeanType, this.customData);
    }

    @Override
    public final Map<String, Object> getCustomData() {
        return customData;
    }

    @Override
    public final void setCustomData(Map<String, Object> customData) {
        this.customData = customData;
    }

    @Override
    public final void setCustomData(OwnPairs<String, Object> customData) {
        this.customData = customData != null ? customData.toMap() : null;
    }

    @Override
    public final void setCustomData(Object javaBean) {
        this.customData = javaBean != null ? ObjKit.allFieldValue(javaBean) : null;
    }

    @Override
    public final void setCustomData(String jsonObject) {
        this.customData = VerifyKit.isJsonObject(jsonObject) ? JsonKit.toEntity(jsonObject,
                new TypeReference<HashMap<String, Object>>() {}) : null;
    }

    @Override
    public final boolean hasRole(String roleKey) {
        if(roleKeyMap != null && !roleKeyMap.isEmpty()) {
            return private_has(this.roleKeyMap, roleKey);
        }
        return false;
    }

    @Override
    public final boolean hasAllRole(String... roleKeys) {
        return private_hasAll(roleKeyMap, roleKeys);
    }

    @Override
    public final boolean hasAllRole(Iterable<String> roleKeys) {
        return private_hasAll(roleKeyMap, roleKeys);
    }

    @Override
    public final boolean hasAnyRole(String... roleKeys) {
        return private_hasAny(roleKeyMap, roleKeys);
    }

    @Override
    public final boolean hasAnyRole(Iterable<String> roleKeys) {
        return private_hasAny(roleKeyMap, roleKeys);
    }

    @Override
    public final boolean hasPerm(String permKey) {
        if(permKeyMap != null && !permKeyMap.isEmpty()) {
            return private_has(this.permKeyMap, permKey);
        }
        return false;
    }

    @Override
    public final boolean hasAllPerm(String... permKeys) {
        return private_hasAll(permKeyMap, permKeys);
    }

    @Override
    public final boolean hasAllPerm(Iterable<String> permKeys) {
        return private_hasAll(permKeyMap, permKeys);
    }

    @Override
    public final boolean hasAnyPerm(String... permKeys) {
        return private_hasAny(permKeyMap, permKeys);
    }

    @Override
    public final boolean hasAnyPerm(Iterable<String> permKeys) {
        return private_hasAny(permKeyMap, permKeys);
    }

    @Override
    public String toString() {
        return this.protected_toStringPropertyString() +
                "uuid=" + uuid +
                ", userId=" + userId +
                ", loginDeviceType=" + loginDeviceType +
                ", loginUserType=" + loginUserType +
                ", userTypeClass=" + userTypeClass +
                ", user=" + user +
                ", roleKeyMap=" + roleKeyMap +
                ", permKeyMap=" + permKeyMap +
                ", routerList=" + routerList +
                ", customData=" + customData;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        GenericAuthUser that = (GenericAuthUser) o;
        return Objects.equals(userId, that.userId) && Objects.equals(loginUserType, that.loginUserType) && Objects.equals(user, that.user) && Objects.equals(userTypeClass, that.userTypeClass)  && Objects.equals(roleKeyMap, that.roleKeyMap) && Objects.equals(permKeyMap, that.permKeyMap) && Objects.equals(routerList, that.routerList) && Objects.equals(customData, that.customData);
    }

    @Override
    public int hashCode() {
        return Objects.hash(userId, loginUserType, user, userTypeClass, roleKeyMap, permKeyMap, routerList, customData);
    }

    /* **************************************************************************************
     *
     *          子类可用/必须实现的逻辑
     *
     * **************************************************************************************
     * */

    @Note("子类 toString 的部分")
    protected abstract String protected_toStringPropertyString();

    @Note("拷贝角色、权限、路由信息到 targetAuthUser 中去")
    @Override
    public final void copyAuthData(AuthUser targetAuthUser) {
        targetAuthUser.setRoleKeyMap(this.roleKeyMap);
        targetAuthUser.setPermKeyMap(this.permKeyMap);
        targetAuthUser.setRouterList(this.routerList);
    }

    @Note("拷贝自定义数据到 targetAuthUser 中去")
    @Override
    public final void copyCustomData(AuthUser targetAuthUser) {
        targetAuthUser.putAllData(this.customData);
    }

    /* **************************************************************************************
     *
     *          自定义数据容器的功能方法
     *
     * **************************************************************************************
     * */

    @Override
    public GenericAuthUser uuid(String uuid) {
        this.setUuid(uuid);
        return this;
    }

    @Override
    public GenericAuthUser userId(Object userId) {
        this.setUserId(userId);
        return this;
    }

    @Override
    public GenericAuthUser userId(String userId) {
        this.setUserId(userId);
        return this;
    }

    @Override
    public GenericAuthUser userId(long userId) {
        this.setUserId(userId);
        return this;
    }

    @Override
    public GenericAuthUser userId(int userId) {
        this.setUserId(userId);
        return this;
    }

    @Override
    public GenericAuthUser loginDeviceType(String loginDeviceType) {
        this.setLoginDeviceType(loginDeviceType);
        return this;
    }

    @Override
    public GenericAuthUser loginDeviceType(LoginDeviceType loginDeviceType) {
        this.setLoginDeviceType(loginDeviceType);
        return this;
    }

    @Override
    public GenericAuthUser loginUserType(String loginUserType) {
        this.setLoginUserType(loginUserType);
        return this;
    }

    @Override
    public GenericAuthUser userTypeClass(String userTypeClassName) {
        this.setUserTypeClass(userTypeClassName);
        return this;
    }

    @Override
    public GenericAuthUser userTypeClass(Class<?> userTypeClass) {
        this.setUserTypeClass(userTypeClass);
        return this;
    }

    @Override
    public GenericAuthUser user(Object user) {
        this.setUser(user);
        return this;
    }

    @Override
    public GenericAuthUser roleKeyMap(Map roleKeyMap) {
        this.setRoleKeyMap(roleKeyMap);
        return this;
    }

    @Override
    public GenericAuthUser roleKeyMap(OwnPairs roleKeyPairs) {
        this.setRoleKeyMap(roleKeyPairs);
        return this;
    }

    @Override
    public GenericAuthUser permKeyMap(Map permKeyMap) {
        this.setPermKeyMap(permKeyMap);
        return this;
    }

    @Override
    public GenericAuthUser permKeyMap(OwnPairs permKeyPairs) {
        this.setPermKeyMap(permKeyPairs);
        return this;
    }

    @Override
    public GenericAuthUser routerList(Iterable routerList) {
        this.setRouterList(routerList);
        return this;
    }

    @Override
    public GenericAuthUser customData(Map<String, Object> customData) {
        this.setCustomData(customData);
        return this;
    }

    @Override
    public GenericAuthUser customData(OwnPairs<String, Object> customData) {
        this.setCustomData(customData);
        return this;
    }

    @Override
    public GenericAuthUser customData(Object javaBean) {
        this.setCustomData(javaBean);
        return this;
    }

    @Override
    public GenericAuthUser customData(String jsonObject) {
        this.setCustomData(jsonObject);
        return this;
    }


    @Override
    public GenericAuthUser putData(String name, Object value) {
        private_lazyLoadCustomDataMap(1);
        this.customData.put(name, value);
        return this;
    }

    @Override
    public GenericAuthUser putAllData(Map customData) {
        if(customData == null || customData.isEmpty()) return this;
        private_lazyLoadCustomDataMap(customData.size());
        private_putCustomDataEntry(customData.entrySet());
        return this;
    }

    @Override
    public GenericAuthUser putAllData(OwnPairs customData) {
        if(customData == null || customData.isEmpty()) return this;
        private_lazyLoadCustomDataMap(customData.size());
        private_putCustomDataEntry(customData.entrySet());
        return this;
    }

    @Override
    public GenericAuthUser putAllData(String jsonObject) {
        if(VerifyKit.isJsonObject(jsonObject)) {
            HashMap<String, Object> map = JsonKit.toEntity(jsonObject, new TypeReference<HashMap<String, Object>>() {});
            if(map.isEmpty()) return this;
            private_lazyLoadCustomDataMap(map.size());
            private_putCustomDataEntry(map.entrySet());
        }
        return this;
    }

    @Override
    public GenericAuthUser putAllData(Object javaBean) {
        if(javaBean == null) return this;
        Map<String, Object> fieldValueMap = ObjKit.allFieldValue(javaBean);
        if(fieldValueMap.isEmpty()) return this;
        private_lazyLoadCustomDataMap(fieldValueMap.size());
        private_putCustomDataEntry(fieldValueMap.entrySet());
        return this;
    }


    @Override
    public GenericAuthUser removeData(String name) {
        if(this.customData != null && !this.customData.isEmpty()) this.customData.remove(name);
        return this;
    }

    @Override
    public GenericAuthUser removeAllData(String... names) {
        if(this.customData != null && !this.customData.isEmpty()) {
            for (String name : names) this.customData.remove(name);
        }
        return this;
    }

    @Override
    public GenericAuthUser removeAllData(Iterable<String> names) {
        if(this.customData != null && !this.customData.isEmpty()) {
            for (String name : names) this.customData.remove(name);
        }
        return this;
    }

    @Override
    public GenericAuthUser clearData() {
        if(this.customData != null && !this.customData.isEmpty()) this.customData.clear();
        return this;
    }

    @Override
    public boolean containsData(String name) {
        if(this.customData != null && !this.customData.isEmpty()) return this.customData.containsKey(name);
        return false;
    }

    @Override
    public boolean containsAllData(String... names) {
        if(this.customData != null && !this.customData.isEmpty()) {
            for (String n : names) {
                if (!this.customData.containsKey(n)) return false;
            }
            return true;
        }
        return false;
    }

    @Override
    public boolean containsAllData(Iterable<String> names) {
        if(this.customData != null && !this.customData.isEmpty()) {
            for (String n : names) {
                if (!this.customData.containsKey(n)) return false;
            }
            return true;
        }
        return false;
    }

    @Override
    public boolean containsAnyData(String... names) {
        if(this.customData != null && !this.customData.isEmpty()) {
            for (String n : names) {
                if (this.customData.containsKey(n)) return true;
            }
            return false;
        }
        return false;
    }

    @Override
    public boolean containsAnyData(Iterable<String> names) {
        if(this.customData != null && !this.customData.isEmpty()) {
            for (String n : names) {
                if (this.customData.containsKey(n)) return true;
            }
            return false;
        }
        return false;
    }

    @Override
    public int dataSize() {
        return (this.customData == null || this.customData.isEmpty()) ? 0 : this.customData.size();
    }

    @Override
    public Object dataGet(String name) {
        if(this.customData == null || this.customData.isEmpty()) return null;
        return this.customData.get(name);
    }

    @Override
    public <V> V dataGet(String name, Class<V> valueType) {
        return (V) this.dataGet(name);
    }

    @Override
    public <V> V dataGet(String name, C<V> valueType) {
        if(this.customData == null || this.customData.isEmpty()) return null;
        return (V) ObjKit.toRealValue(this.dataGet(name), valueType);
    }


    /* **************************************************************************************
     *
     *          私有逻辑
     *
     * **************************************************************************************
     * */

    @Note("将 src 的数据拷贝到 temp 里返回")
    private Map<String, Object> private_getTempMap(Map src) {
        if(src == null || src.isEmpty()) return null;
        Map<String, Object> temp = new HashMap<>((int) (src.size() / 0.75) + 1);
        for(Object o : src.entrySet()) {
            Map.Entry e = (Map.Entry) o;
            temp.put(e.getKey().toString(), e.getValue());
        }
        return temp;
    }

    @Note("将 src 的数据拷贝到 temp 里返回")
    private Map<String, Object> private_getTempMap(OwnPairs src) {
        if(src != null && !src.isEmpty()) {
            Map<String, Object> temp = new HashMap<>((int) (src.size() / 0.75) + 1);
            Set set = src.entrySet();
            for(Object o : set) {
                Map.Entry e = (Map.Entry) o;
                temp.put(e.getKey().toString(), e.getValue());
            }
            return temp;
        }
        return null;
    }

    @Note("将自定义的数据放入集合内")
    private void private_putCustomDataEntry(Set entrySet) {
        for (Object o : entrySet) {
            Map.Entry e = (Map.Entry) o;
            this.customData.put(ObjKit.asStringValue(e.getValue(), null),
                    e.getValue());
        }
    }

    @Note("懒加载自定义数据 Map 集合")
    private void private_lazyLoadCustomDataMap(int initSize) {
        if(this.customData == null) {
            this.customData = new HashMap<>(MapEnum.calcInitSize(initSize));
        }
    }

    @Note("判断权限/角色 key 是否在指定的集合内")
    private static boolean private_has(Map<String, ?> map, String key) {
        if(key != null && !key.isEmpty()) return map.containsKey(key);
        return false;
    }

    @Note("判断 keys 里的所有权限/角色 key 是否在指定的集合内")
    private static boolean private_hasAll(Map<String, ?> map, String[] keys) {
        if(map != null && !map.isEmpty() && keys != null && keys.length != 0) {
            for(String key : keys) if(!private_has(map, key)) return false;
            return true;
        }
        return false;
    }

    @Note("判断 keys 里的所有权限/角色 key 是否在指定的集合内")
    private static boolean private_hasAll(Map<String, ?> map, Iterable<String> keys) {
        if(map != null && !map.isEmpty()) {
            int size = RowKit.getIterableSize(keys);
            if(size != 0) {
                for(String key : keys) if(!private_has(map, key)) return false;
                return true;
            }
            return false;
        }
        return false;
    }

    @Note("判断 keys 里的任意一个有权限/角色 key 是否在指定的集合内")
    private static boolean private_hasAny(Map<String, ?> map, String[] keys) {
        if(map != null && !map.isEmpty() && keys != null && keys.length != 0) {
            for(String key : keys) if(private_has(map, key)) return true;
            return false;
        }
        return false;
    }

    @Note("判断 keys 里的任意一个权限/角色 key 是否在指定的集合内")
    private static boolean private_hasAny(Map<String, ?> map, Iterable<String> keys) {
        if(map != null && !map.isEmpty()) {
            int size = RowKit.getIterableSize(keys);
            if(size != 0) {
                for(String key : keys) if(private_has(map, key)) return true;
                return false;
            }
            return false;
        }
        return false;
    }

}
